package com.wooshow.base.export;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.wooshow.base.all.NameGen;

public class ExportBase implements NameGen {

	private static Log log = LogFactory.getLog(ExportBase.class);
	
	private static WritableFont WF_NOBOLD = new jxl.write.WritableFont(WritableFont.TIMES, 18, WritableFont.NO_BOLD, true); 
	private static WritableCellFormat WCF_NOBOLD = new jxl.write.WritableCellFormat(WF_NOBOLD); 
	private static WritableFont WF_BOLD = new jxl.write.WritableFont(WritableFont.TIMES, 18, WritableFont.NO_BOLD, true); 
	private static WritableCellFormat WCF_BOLD = new jxl.write.WritableCellFormat(WF_BOLD); 
	
	private NameGen nameGen;

	public void export2Xls(List<Bean4Export> exports, HttpServletResponse res) {
		if (exports == null || exports.size() == 0) {
			return;
		}
		
		try {
			int sheetSize = exports.size();
			String fileName = URLEncoder.encode(nameGen.generatorName(null) + ".xls", "utf-8");
			res.setContentType("application/x-msdownload");
			res.setHeader("Content-Disposition", "attachment;Filename=" + fileName);
			OutputStream outStream;
			outStream = res.getOutputStream();
			WritableWorkbook wwb;
			wwb = Workbook.createWorkbook(outStream);
			for (int i = 0; i < sheetSize; i++) {
				Bean4Export thisExport = exports.get(i);
				if (thisExport.getClazz() == null || thisExport.getDatas() == null || thisExport.getMap4Field() == null
				        || thisExport.getTitles() == null) {
					continue;
				}
				createSheet(wwb, thisExport.getSheetName(), thisExport, i);
			}
			wwb.write();
			wwb.close();
		} catch (UnsupportedEncodingException e) {
			log.error(e);
		} catch (IOException e) {
			log.error(e);
		} catch (WriteException e) {
			log.error(e);
		}

	}

	private static void createSheet(WritableWorkbook wwb, String sheetName, Bean4Export thisExport, int i) {
		WritableSheet ws = wwb.createSheet(sheetName, i);
		if (thisExport.getClazz() == null || thisExport.getDatas() == null || thisExport.getMap4Field() == null || thisExport.getTitles() == null) {
			return;
		}
		int rows = 0;
		int fieldSize = thisExport.getTitles().length;
		int recSize = thisExport.getDatas().size();
		setHeader(ws, rows++, thisExport.getTitles());

		for (int j = 0; j < recSize; j++) {
			setData(ws, rows++, thisExport.getMap4Field(), fieldSize, thisExport.getDatas().get(j), thisExport.getClazz());
		}
	}

	private static void setHeader(WritableSheet ws, int rownum, String[] titles) {
		try {
			for (short i = 0; i < titles.length; i++) {
				Label cell = new Label(i, rownum, titles[i], WCF_NOBOLD);
				ws.addCell(cell);
			}
		} catch (Exception e) {

		}
	}

	private static void setData(WritableSheet ws, int rownum, Map<Short, String> map4Field, int fieldSize, Object data, Class clazz) {
		if (data == null | map4Field == null || fieldSize <= 0) {
			return;
		}
		for (int i = 0; i < fieldSize; i++) {
			try {
				String fieldName = map4Field.get(i).toString();
				String[] fieldNames = fieldName.split("\\.");
				Object value = data;
				Class thisClazz = clazz;
				for (int j = 0; j < fieldNames.length; j++) {
					String thisFieldNameOriginal = fieldNames[j];
					String thisFieldName = thisFieldNameOriginal;
					int index = thisFieldNameOriginal.indexOf("[");
					int subIndex = 0;
					if (index >= 0) {
						int length = thisFieldNameOriginal.length();
						thisFieldName = thisFieldNameOriginal.substring(0, index);
						subIndex = Integer.valueOf(thisFieldNameOriginal.substring(index + 1, length - 1));
					}
					Method method = thisClazz.getMethod("get" + thisFieldName.substring(0, 1).toUpperCase() + thisFieldName.substring(1));
					value = method.invoke(value);
					if (index >= 0) {
						value = ((Object[]) value)[subIndex];
					}
					thisClazz = value.getClass();
				}

				try {
					//to do, check the date format and convert if needed
				} catch (Exception e) {

				}
				Label cell = new Label(i, rownum, value.toString(), WCF_BOLD);
				ws.addCell(cell);
			} catch (Exception ex) {
				log.error(ex);
			}
		}
	}

	public String generatorName(Object object) {
		String name = "export";
		return name;
	}

	public NameGen getNameGen() {
		if (nameGen == null) {
			nameGen = this;
		}
		return nameGen;
	}

	public void setNameGen(NameGen nameGen) {
		this.nameGen = nameGen;
	}
}
